package cn.iocoder.yudao.module.engine.util;

import jakarta.annotation.Resource;
import jakarta.validation.ValidationException;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

@Component
public class ValidateUtils {
    @Resource
    private Validator validator;

    public void validate(Object fieldValue) {
        final String fieldName = fieldValue.getClass().getSimpleName();

        // 手动进行校验
        Errors errors = new BeanPropertyBindingResult(fieldValue, fieldName);
        validator.validate(fieldValue, errors);
        if (errors.hasErrors()) {
            // 如果校验失败，可以根据实际需求处理，比如抛出异常
            throw new ValidationException(errors.getAllErrors().get(0).getDefaultMessage());
        }
    }

    /**
     * 校验A的所有字段是否在B中存在
     *
     * @param classA
     * @param classB
     */
    public static void validateAllFieldsExisted(Class<?> classA, Class<?> classB) {
        final List<String> missingFields = findMissingFields(classA, classB);
        if (!missingFields.isEmpty()) {
            throw new ValidationException("Missing fields in class " + classB.getSimpleName() + ": " + missingFields);
        }
    }

    private static List<String> findMissingFields(Class<?> classA, Class<?> classB) {
        List<String> missingFields = new ArrayList<>();
        compareFields(classA, classB, missingFields);
        return missingFields;
    }

    private static void compareFields(Class<?> classA, Class<?> classB, List<String> missingFields) {
        Field[] fieldsA = classA.getDeclaredFields();
        Field[] fieldsB = classB.getDeclaredFields();

        for (Field fieldA : fieldsA) {
            boolean found = false;
            for (Field fieldB : fieldsB) {
                if (fieldA.getName().equals(fieldB.getName()) && fieldA.getType().equals(fieldB.getType())) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                missingFields.add(classA.getSimpleName() + "." + fieldA.getName());
            }
        }

        // Recursively check fields of inner classes
        Class<?>[] innerClassesA = classA.getDeclaredClasses();
        Class<?>[] innerClassesB = classB.getDeclaredClasses();

        for (Class<?> innerClassA : innerClassesA) {
            boolean foundInnerClass = false;
            for (Class<?> innerClassB : innerClassesB) {
                if (innerClassA.getSimpleName().equals(innerClassB.getSimpleName())) {
                    foundInnerClass = true;
                    compareFields(innerClassA, innerClassB, missingFields);
                    break;
                }
            }
            if (!foundInnerClass) {
                missingFields.add(innerClassA.getSimpleName());
            }
        }
    }

}
